package net.midnighttd.engine;

import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import java.util.HashMap;
import java.util.Timer;
import java.util.TimerTask;
import java.awt.*;
import net.midnighttd.engine.entity.*;
import net.midnighttd.engine.map.*;
import net.midnighttd.engine.view.sprite.*;


public class Engine {
    private Timer gameLoopTimer = new Timer("GameLoop");
    private MapManager maps = new MapManager();
    private HashMap<String, Point> points = new HashMap<String, Point>();
    private SpriteManager spriteManager = new SpriteManager();
    private EntityManager entityManager = new EntityManager(this);

    public void init(String filename) {
        loadFromXML(ResourceManager.getXML(filename));
    }

    public void loadFromXML(Element e) {
        loadEnts(e.getElementsByTagName("entities"));
        loadMaps(e.getElementsByTagName("map"));
        loadPoints(e.getElementsByTagName("point"));
    }

    private void loadEnts(NodeList ents) {
        for(int i = 0; i < ents.getLength(); i++) {
            if(ents.item(i).getNodeType() != Node.ELEMENT_NODE) continue;
            Element tile = (Element)ents.item(i);

            entityManager.loadFromXML(ResourceManager.getXML(tile.getAttribute("src")));
        }
    }

    private void loadMaps(NodeList maps) {
        for(int i = 0; i < maps.getLength(); i++) {
            if(maps.item(i).getNodeType() != Node.ELEMENT_NODE) continue;
            Element tile = (Element)maps.item(i);

            this.maps.add(new Map(ResourceManager.getXML(tile.getAttribute("src"))));
        }
    }

    private void loadPoints(NodeList points) {
        for(int i = 0; i < points.getLength(); i++) {
            if(points.item(i).getNodeType() != Node.ELEMENT_NODE) continue;
            Element point = (Element)points.item(i);

            Point p = new Point(Integer.valueOf(point.getAttribute("x")),Integer.valueOf(point.getAttribute("y")));
            this.points.put(point.getAttribute("name"), p);
        }
    }

    public EntityManager getEntityManager() {
        return entityManager;
    }

    public Point getPoint(String name) {
        Point p = points.get(name);
        if(p == null) throw new Error("Could not load point '" + name + "'");
        return p;
    }

    public void gameLoop() {
        for(Entity e: getEntityManager().getActiveEnts()) {
            e.gameLogic();
        }

        spriteManager.updateAll();
    }

    public boolean isPassable(int x, int y) {
        return maps.isPassable(x, y) && entityManager.isPassable(x, y);
    }


    public MapManager getMapManager() {
        return maps;
    }

    public void start() {
        stop();
        gameLoopTimer.scheduleAtFixedRate(new GameLoopTimer(), 0l, 10l);
    }

    public void stop() {
        gameLoopTimer.purge();
    }

    public SpriteManager getSpriteManager() {
        return spriteManager;
    }

    private class GameLoopTimer extends TimerTask {
        public void run() {
            gameLoop();
        }
    }
}
